package drds.plus.sql_process.abstract_syntax_tree.execute_plan.query;

import drds.plus.sql_process.abstract_syntax_tree.execute_plan.ExecutePlanImpl;
import drds.plus.sql_process.abstract_syntax_tree.expression.bind_value.BindValue;
import drds.plus.sql_process.abstract_syntax_tree.expression.item.Item;
import drds.plus.sql_process.abstract_syntax_tree.expression.item.function.Filter;
import drds.plus.sql_process.abstract_syntax_tree.expression.order_by.OrderBy;
import drds.plus.sql_process.utils.OptimizerUtils;

import java.util.Collections;
import java.util.List;

public abstract class QueryImpl extends ExecutePlanImpl<Query> implements Query<Query> {

    protected Filter valueFilter;
    protected Filter having;
    protected Filter subQueryFilter;
    protected List<OrderBy> orderByList = Collections.emptyList();
    protected List<OrderBy> groupByList = Collections.emptyList();
    protected Comparable limitFrom;
    protected Comparable limitTo;
    protected List<Item> itemList = Collections.emptyList();
    protected String alias;
    /**
     * 查询模式，并行？串行？
     */
    protected QueryConcurrencyWay queryConcurrencyWay = QueryConcurrencyWay.sequential;

    /**
     * 能否被合并成一条sql，默认可以
     */
    protected Boolean canMerge = true;

    /**
     * 是否显式使用临时表，默认不可以
     */
    protected Boolean useTemporaryTableExplicit = false;
    protected Boolean isSubQuery = false;
    protected boolean isTopQuery = false;
    /**
     * 是否为存在聚合信息，比如出现limit/group by
     * by/count/max等，此节点就会被标记为true，不允许进行join sort join的展开优化
     */
    protected boolean isExistAggregate = false;

    /**
     * 非column=column的join列
     */
    protected Filter otherJoinOnFilter;
    protected Long subQueryOnFilterId = 0L;
    protected boolean isCorrelatedSubQuery = false;
    protected LockMode lockModel = LockMode.undefined;

    public Filter getValueFilter() {
        return valueFilter;
    }

    public void setValueFilter(Filter valueFilter) {
        this.valueFilter = valueFilter;

    }

    public Filter getSubQueryFilter() {
        return subQueryFilter;
    }

    public void setSubQueryFilter(Filter subQueryFilter) {
        this.subQueryFilter = subQueryFilter;

    }

    public List<Item> getItemList() {
        return itemList;
    }

    public void setSelectItemList(List<Item> itemList) {
        this.itemList = itemList;

    }


    public List<OrderBy> getOrderByList() {
        return orderByList;
    }

    public void setOrderByList(List<OrderBy> orderByList) {
        this.orderByList = orderByList;

    }

    public Comparable getLimitFrom() {
        return limitFrom;
    }

    public void setLimitFrom(Comparable limitFrom) {
        this.limitFrom = limitFrom;

    }

    public Comparable getLimitTo() {
        return limitTo;
    }

    public void setLimitTo(Comparable limitTo) {
        this.limitTo = limitTo;

    }

    public List<OrderBy> getGroupByList() {
        return groupByList;
    }

    public void setGroupByList(List<OrderBy> groupByList) {
        this.groupByList = groupByList;

    }

    public void setAlias(String alias) {
        this.alias = alias;

    }

    public String getAlias() {
        return alias;
    }

    public void setCanMerge(Boolean canMerge) {
        this.canMerge = canMerge;

    }

    public Boolean canMerge() {
        return canMerge;
    }

    public void setExplicitUseTemporaryTable(Boolean useTemporaryTableExplicit) {
        this.useTemporaryTableExplicit = useTemporaryTableExplicit;

    }

    public Boolean isExplicitUseTemporaryTable() {
        return useTemporaryTableExplicit;
    }

    public Boolean isSubQuery() {
        return isSubQuery;
    }

    public void setIsSubQuery(Boolean isSubQuery) {
        this.isSubQuery = isSubQuery;

    }

    public Filter getHaving() {
        return having;
    }

    public void having(Filter having) {
        this.having = having;

    }

    public boolean isTopQuery() {
        return isTopQuery;
    }

    public void setTopQuery(boolean topQuery) {
        this.isTopQuery = topQuery;

    }

    public void setQueryConcurrency(QueryConcurrencyWay queryConcurrencyWay) {
        this.queryConcurrencyWay = queryConcurrencyWay;

    }

    public QueryConcurrencyWay getQueryConcurrencyWay() {
        return queryConcurrencyWay;
    }

    public boolean isExistAggregate() {
        return isExistAggregate;
    }

    public void setExistAggregate(boolean isExistAggregate) {
        this.isExistAggregate = isExistAggregate;

    }

    public Filter getOtherJoinOnFilter() {
        return otherJoinOnFilter;
    }

    public void setOtherJoinOnFilter(Filter otherJoinOnFilter) {
        this.otherJoinOnFilter = otherJoinOnFilter;

    }

    public Long getSubQueryFilterId() {
        return subQueryOnFilterId;
    }

    public void setSubQueryFilterId(Long subQueryOnFilterId) {
        this.subQueryOnFilterId = subQueryOnFilterId;

    }

    public boolean isCorrelatedSubQuery() {
        return isCorrelatedSubQuery;
    }

    public void setCorrelatedSubQuery(boolean isCorrelatedSubQuery) {
        this.isCorrelatedSubQuery = isCorrelatedSubQuery;

    }

    protected void copySelfTo(QueryImpl queryTree) {
        queryTree.setRequestId(this.getRequestId());
        queryTree.setSubRequestId(this.getSubRequestId());
        queryTree.setRequestHostName(this.getRequestHostName());
        queryTree.setConsistent(this.isConsistent());
        queryTree.setQueryConcurrency(this.getQueryConcurrencyWay());
        queryTree.setAlias(this.getAlias());
        queryTree.setCanMerge(this.canMerge());
        queryTree.setExplicitUseTemporaryTable(this.isExplicitUseTemporaryTable());
        queryTree.setThreadNo(getThreadNo());
        queryTree.setStreaming(this.isStreaming());
        queryTree.setSql(this.getSql());
        queryTree.setIsSubQuery(this.isSubQuery());
        queryTree.setTopQuery(this.isTopQuery());
        queryTree.setDataNodeId(this.getDataNodeId());
        queryTree.setExistAggregate(this.isExistAggregate());
        queryTree.setLazyLoad(this.isLazyLoad());
        queryTree.setSelectItemList(OptimizerUtils.copySelectItemList((this.getItemList())));
        queryTree.setGroupByList(OptimizerUtils.copyOrderByList(this.getGroupByList()));
        queryTree.setOrderByList(OptimizerUtils.copyOrderByList(this.getOrderByList()));
        queryTree.setValueFilter(OptimizerUtils.copyFilter(this.getValueFilter()));
        queryTree.having(OptimizerUtils.copyFilter(this.getHaving()));
        queryTree.setOtherJoinOnFilter(OptimizerUtils.copyFilter(this.getOtherJoinOnFilter()));
        queryTree.setLockMode(this.lockModel);
        if (this.getLimitFrom() instanceof BindValue) {
            queryTree.setLimitFrom(((BindValue) this.getLimitFrom()).copy());
        } else {
            queryTree.setLimitFrom(this.getLimitFrom());
        }

        if (this.getLimitTo() instanceof BindValue) {
            queryTree.setLimitTo(((BindValue) this.getLimitTo()).copy());
        } else {
            queryTree.setLimitTo(this.getLimitTo());
        }
    }

    public LockMode getLockMode() {
        return lockModel;
    }

    public void setLockMode(LockMode lockModel) {
        this.lockModel = lockModel;

    }

}
